package com.aizuda.easyManagerTool.service.docker.impl;

import cn.hutool.core.util.ObjectUtil;
import com.aizuda.easy.security.exp.impl.BasicException;
import com.aizuda.easyManagerTool.domain.vo.docker.DockerManagerVO;
import com.aizuda.easyManagerTool.domain.vo.docker.DockerMonitorVO;
import com.aizuda.easyManagerTool.service.docker.DockerMonitorService;
import com.alibaba.fastjson.JSON;
import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.model.StatisticNetworksConfig;
import com.github.dockerjava.api.model.Statistics;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class DockerMonitorServiceImpl implements DockerMonitorService {

    @Override
    public String monitor(Integer id,String containerId) {
        DockerManagerVO dockerManagerVO = DockerManager.get(id);
        final Statistics[] json = {null};
        dockerManagerVO.getDockerClient().statsCmd(containerId).exec(new ResultCallback.Adapter<Statistics>() {
            @SneakyThrows(BasicException.class)
            @Override
            public void onNext(Statistics statistics) {
                json[0] = statistics;
                throw new BasicException(500,"停止运行");
            }
            @Override
            public void onError(Throwable throwable) {
                if(throwable instanceof BasicException){
                    BasicException basicException = (BasicException)throwable;
                    return;
                }
               log.error("docker 拉取异常，{}",throwable.getMessage());
            }
        });
        int i = 3;
        while(true){
            if(json[0] != null || i-- < 1){
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {}
        }
        if(ObjectUtil.isEmpty(json[0])){
            json[0] = new Statistics();
        }
        return JSON.toJSONString(toDockerMonitorVO(json[0]));
    }


    private DockerMonitorVO toDockerMonitorVO(Statistics statistics){
        DockerMonitorVO dockerMonitorVO = new DockerMonitorVO();
        if(ObjectUtil.isNotEmpty(statistics.getCpuStats())){
            long totalUsage = statistics.getCpuStats().getCpuUsage().getTotalUsage();
            long onlineCpus = statistics.getCpuStats().getOnlineCpus();
            long systemCpuUsage = statistics.getCpuStats().getSystemCpuUsage();
            dockerMonitorVO.setCpuUse((double) ((totalUsage * onlineCpus) / systemCpuUsage) * 100);
        }
        if(ObjectUtil.isNotEmpty(statistics.getMemoryStats())){
            long limit = statistics.getMemoryStats().getLimit();
            long usage = statistics.getMemoryStats().getUsage();
            dockerMonitorVO.setMemoryUse((double) (usage / limit * 100));
        }
        Map<String,DockerMonitorVO.NetWork> map = new HashMap<>();
        if(ObjectUtil.isNotEmpty(statistics.getNetworks())){
            statistics.getNetworks().entrySet().stream().forEach(i -> {
                String key = i.getKey();
                StatisticNetworksConfig value = i.getValue();
                Double rx =  (value.getRxBytes() / Math.pow(1024, 2));
                Double tx =  (value.getTxBytes() / Math.pow(1024, 2));
                map.put(key, new DockerMonitorVO.NetWork(rx,tx,"MB"));
            });
            dockerMonitorVO.setNetWork(map);
        }
        return dockerMonitorVO;
    }

}
